/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package main;

import helper.Utilities;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
import model.Handshake;
import model.Message;
import model.Torrent;

/**
 *
 * @author Hallucinogen
 */
public class PeerHandler extends Thread {
    public PeerHandler(Socket clientSocket, ArrayList<Torrent> listTorrent) {
        m_Peer = null;
        m_Socket = clientSocket;
        m_Running = false;
        arrayTor = listTorrent;
    }

    @Override
    public void run() {
        try {
            System.out.println("Handler created");
            m_Socket.setSoTimeout(5000);
            BufferedOutputStream out = new BufferedOutputStream(m_Socket.getOutputStream());
            InputStream in = m_Socket.getInputStream();
            StringBuilder sb = new StringBuilder();
            int input = -1;

            boolean handshake = false;
            if ((input = in.read()) != -1) {

                System.out.println("[Peer Handler] reading handshake");
                sb.append((char)input);
                /** read protocol name */
                for (int i = 0; i < input; ++i)
                    sb.append((char)in.read());

                /** read reserved */
                for (int i = 0; i < 8; ++i)
                    sb.append((char)in.read());

                /** read sha of filename */
                for (int i = 0; i < 40; ++i)
                    sb.append((char)in.read());
            }

            //if (input == -1) return;
            
            Handshake hand = Handshake.fromString(sb.toString());


            System.out.println("[Peer Handler] handshake dibaca gan, fileHash = " + hand.getFileName());

            for (int i = 0; i < arrayTor.size(); ++i) {
                // kalo ternyata file nya di share juga
                try {
                    System.out.println(arrayTor.get(i).getFileName() + " " + Utilities.convertToSHA1(arrayTor.get(i).getFileName()));
                    if (Utilities.convertToSHA1(arrayTor.get(i).getFileName()).equals(hand.getFileName())) {
                        m_Torrent = arrayTor.get(i);
                        handshake = true;
                    }
                } catch (Exception ex) {
                    
                }
            }

            //ConnectionHandler ch = new ConnectionHandler(m_Socket, arrayTor, m_Peer);
            //ch.run();

            if (handshake) {
                // kirim message kepemilikan pertama
                m_Running = true;
                BufferedOutputStream bos = new BufferedOutputStream(m_Socket.getOutputStream());

                boolean[] availablePieces = m_Torrent.compareDownloadedFile(m_Torrent.getResultPath());
                sb = new StringBuilder();
                int length = availablePieces.length + 1;

                for (int j = 0; j < availablePieces.length; ++j) {
                    if (availablePieces[j])
                        sb.append((char)1);
                    else
                        sb.append((char)0);
                }

                Message message = new Message(length, Message.MESSAGE_BITFIELD, sb.toString());
                bos.write(message.toByte());
                bos.flush();
            }  else {
                
            }

            while (m_Running) {
                input = -1;
                if ((input = in.read()) != -1) {
                    /** baca message length */
                    int len = input;
                    String temp = "" + input;
                    for (int j = 1; j < 4; ++j){
                        input = in.read();
                        len = len * 256 + input;
                        temp = temp + (char)input;
                    }

                    sb = new StringBuilder();
                    /** baca sisanya */
                    for (int j = 0; j < len; ++j) {
                        sb.append((char)in.read());
                    }
                    Message message = Message.fromString(temp + sb.toString());
                    /// TODO : process message

                    final int messageType = message.getType();

                    switch (messageType) {
                        case Message.MESSAGE_REQUEST:
                            String content = message.getContent();
                            int index = 0;
                            int begin = 0;
                            int length = 0;

                            for (int i = 0; i < 4; ++i)
                                index = index * 256 + (int)content.charAt(i);

                            for (int i = 4; i < 8; ++i)
                                begin = begin * 256 + (int)content.charAt(i);

                            for (int i = 8; i < 12; ++i)
                                length = length * 256 + (int)content.charAt(i);

                            byte[] res = m_Torrent.getCompletedPiece(index);

                            begin   = 0;

                            sb = new StringBuilder();

                            // masukin index
                            sb.append(content.charAt(0));
                            sb.append(content.charAt(1));
                            sb.append(content.charAt(2));
                            sb.append(content.charAt(3));

                            // masukin begin
                            sb.append(0);
                            sb.append(0);
                            sb.append(0);
                            sb.append(0);

                            for (int i = 0; i < res.length; ++i)
                                sb.append((char)res[i]);

                            String str = sb.toString();

                            Message response = new Message(str.length() + 1, Message.MESSAGE_PIECE, str);

                            BufferedOutputStream bos = new BufferedOutputStream(m_Socket.getOutputStream());

                            bos.write(response.toByte());

                            bos.flush();

                            break;

                        case Message.MESSAGE_BITFIELD:
                            break;
                    }
                } else {
                    // end stream
                }
            }
        } catch (IOException ex) {
            
        }

        try {
            m_Socket.close();
        } catch (IOException iEx) {
            
        }
    }

    public boolean isRunning(){
        return m_Running;
    }

    public void setRunning(boolean running) {
        m_Running = running;
    }

    public static void main(String[] args) {
        Peer p = new Peer("127.0.0.1");

        PeerHandler pd = new PeerHandler(null, null);
        pd.start();

    }
    
    private Peer m_Peer;
    private Socket m_Socket;
    private boolean m_Running;
    public ArrayList<Torrent> arrayTor = new ArrayList<Torrent>();
    private Torrent m_Torrent;
}
/*
class ConnectionHandler implements Runnable {
    private Socket socket;
    private ArrayList<Torrent> listTor = new ArrayList<Torrent>();
    private Peer per = new Peer();

    public ConnectionHandler(Socket socket, ArrayList<Torrent> listTorrent, Peer p) {
        this.socket = socket;
        this.listTor = listTorrent;
        this.per = p;

        Thread t = new Thread(this);
        t.start();
    }

    public void run() {
        try
        {
            //
            // Read a message sent by client application
            //
            ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
            String message = (String) ois.readObject();
            System.out.println("Message Received: " + message);

            //
            // Send a response information to the client application
            //


            
            System.out.println(message);
            String[] parsing = message.split("");

            boolean punya = false;
            for(int y=0;y<this.listTor.size();y++){
                if(parsing[parsing.length-1]==this.listTor.get(y).getFileName()){
                    punya=true;
                        
                        ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                        oos.writeObject("");
                        oos.close();
                    break;
                }
            }

            
                

            

            ois.close();
            
            socket.close();

            System.out.println("Waiting for client message...");
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}*/
